#include "LogicAgent.h"
#include "GateServer.h"
#include "GateServer.h"
LogicAgent::LogicAgent()
{
}

LogicAgent::~LogicAgent()
{
}

void LogicAgent::OnDisConnectEvent(const SOCKET& _sockFd)
{
	RemoteAgent::OnDisConnectEvent(_sockFd);
}

void LogicAgent::OnReadNetData(const SOCKET& _sockFd)
{
	m_recvCount++;
	auto result = GateServer::GetInstance()->GetThreadPool().Exec(
		std::bind(&LogicAgent::NetPackRead, this, std::placeholders::_1), _sockFd
	);
	result.wait();
	result.get();
}

void LogicAgent::OnWriteNetData(const SOCKET& _sockFd)
{
	auto result = GateServer::GetInstance()->GetThreadPool().Exec(
		std::bind(&LogicAgent::NetPackSend, this, std::placeholders::_1), _sockFd
	);
	result.wait();
	result.get();
}

void LogicAgent::NetPackRead(const SOCKET& _fd)
{
	GateMsgHead hdr;
	m_recvBuff.TailorFont(m_recvBuff.readPos());
	if (m_recvBuff.writeAvailable() > 0)
	{
		int32_t len = ::recv(_fd, m_recvBuff.writePointer(), m_recvBuff.writeAvailable(), 0);
		if (len <= 0)
		{
			OnDisConnectEvent(_fd);
			return;
		}
		m_recvBuff.setWritePos(len);
	}
	do
	{
		memset(&hdr, 0, CM_MSG_SIZE);
		if (m_recvBuff.readAvailable() < CM_MSG_SIZE)
		{
			break;
		}
		m_recvBuff.readData(&hdr, CM_MSG_SIZE, true);
		if (m_recvBuff.readAvailable() < hdr.length + CM_MSG_SIZE)
		{
			break;
		}
		m_recvBuff.setReadPos(CM_MSG_SIZE);

		NetPackArray packBody;
		m_recvBuff.readData(packBody.data(), hdr.length);
		m_recvBuff.TailorFont(CL_MSG_SIZE);

		packBody.setWritePos(hdr.length);

		if (hdr.cmd >= SERVER_PRO_MAX || hdr.cmd < SERVER_PRO_MIN || hdr.encrypt != PROTOCOL_ENCRYPT)
		{
			LogPrint(LogType::ERR, "recv fail msg data~");
			continue;
		}
		if (hdr.length >= 1024 * 1024)
		{
			LogPrint(LogType::ERR, "recv pack too lang,size:<%d>~", hdr.length);
			continue;
		}
		m_msgCount++;
		GateServer::GetInstance()->FrowordToClient(hdr.clientID, hdr.cmd, packBody.data(), packBody.size());
	} while (!IsStop());
}

void LogicAgent::NotTimeMsg()
{
	auto t = m_timeStep.GetElapsedSecond();
	if (t > 1.0f)
	{
		LogPrint(LogType::TIP, "logic agent: time:<%lf>,recv<%d>,packsize<%d>,sendsize<%d>~", t, int(m_recvCount / t), int(m_msgCount / t), int(m_sendCount / t));
		m_sendCount = 0;
		m_msgCount = 0;
		m_recvCount = 0;
		m_timeStep.Update();
	}
}

void LogicAgent::NetPackSend(const SOCKET& _fd)
{
	if (m_sendList.empty() || !Connect())
		return;

	std::list<NetPackArray> netPacks;
	{
		std::lock_guard<std::mutex> loack(m_mutex);
		netPacks.swap(m_sendList);
		m_sendList.clear();
	}
	while (!netPacks.empty() && Connect())
	{
		auto& item = netPacks.front();
		auto result = ::send(_fd, item.data(), item.size(), 0);
		if (result <= 0)
		{
			auto err = WSAGetLastError();
			if (err == 10035)
			{
				LogPrint(LogType::WAR, "socket write buff full");
				std::this_thread::sleep_for(std::chrono::microseconds(1));
			}
			else
			{
				OnDisConnectEvent(_fd);
				printf("send net pack fail,err:%d~\n", err);
			}
			continue;
		}
		netPacks.pop_front();
	}
}
